package com.ruoyi.framework.sse;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * SSE工具类
 * @author qjy
 */
@Component
@Slf4j
public class SseUtils {

    private static final Map<Long, SseEmitter> SSE_EMITTER_MAP = new ConcurrentHashMap<>();

    public SseEmitter connect(Long userId) {
        if (SSE_EMITTER_MAP.containsKey(userId)){
            SseEmitter sseEmitter = SSE_EMITTER_MAP.get(userId);
            SSE_EMITTER_MAP.remove(userId);
            sseEmitter.complete();
        }
        try{
            String str = UUID.randomUUID().toString();
            String temp = str.substring(0,8) + str.substring(9,13)+str.substring(14,18)+str.substring(19,23)+str.substring(24);
            //设置超时时间 0表示不过期 默认60秒
            SseEmitter sseEmitter = new SseEmitter(1200 * 1000L);
            sseEmitter.send(SseEmitter.event().id(temp).data("连接成功"));
            //注册回调
            sseEmitter.onCompletion(completionCallBack(userId));
            sseEmitter.onTimeout(timeoutCallBack(userId));
            SSE_EMITTER_MAP.put(userId, sseEmitter);
            log.info("创建 sse 连接完成.当前用户:{}",userId);
            return sseEmitter;
        }catch (Exception e){
            log.error("创建 sse 连接异常.当前用户:{}",userId,e);
            throw  new RuntimeException("创建 sse 连接异常.当前用户"+userId,e);
        }
    }

    /**
     * 获取SSE Emitter Map
     * @return SSE Emitter Map
     */
    public Map<Long, SseEmitter> getSseEmitterMap() {
        return SSE_EMITTER_MAP;
    }

    /**
     * 删除连接
     * @param userId 用户ID
     */
    public void deleteUser(Long userId) {
        removeUser(userId);
    }

    /**
     * 给指定用户发送消息
     * @param userId 用户ID
     * @param messageId 消息ID
     * @param message 消息内容
     * @return 发送成功返回true,失败返回false
     */
    public boolean sendMessage(Long userId,String messageId,String message){
        if (SSE_EMITTER_MAP.containsKey(userId)){
            SseEmitter sseEmitter = SSE_EMITTER_MAP.get(userId);
            try {
                sseEmitter.send(SseEmitter.event().id(messageId).data(message));
                log.info("用户: {} 发送消息成功,消息id:{},消息内容:{}", userId,messageId,message);
                return true;
            } catch (IOException e) {
                SSE_EMITTER_MAP.remove(userId);
                log.error("用户{},消息id:{},推送异常:{}", userId,messageId, e.getMessage());
                sseEmitter.complete();
                return false;
            }

        }else {
            log.info("用户: {} 未上线", userId);
        }
        return false;
    }

    private Runnable timeoutCallBack(Long userId) {
        return () -> {
            log.info("用户: {} 连接超时", userId);
            removeUser(userId);
        };
    }

    private Runnable completionCallBack(Long userId) {
        return () -> {
            log.info("结束用户连接: {}" , userId);
            removeUser(userId);
        };
    }

    /**
     * 移除用户
     * @param userId 用户ID
     */
    private void removeUser(Long userId) {
        if (SSE_EMITTER_MAP.containsKey(userId)){
            SseEmitter sseEmitter = SSE_EMITTER_MAP.get(userId);
            SSE_EMITTER_MAP.remove(userId);
            sseEmitter.complete();
            log.info("用户: {} 连接关闭了", userId);
        }else {
            log.info("用户: {} 连接已关闭", userId);
        }
    }


}
